package com.gitee.liuzhi.design.structure;

import com.gitee.liuzhi.common.model.Student;
import lombok.extern.slf4j.Slf4j;

/**
 * @Author liuzhi
 * @Date 2023/8/27 09:53
 * @Version 1.0
 * @Description 适配器模式 Adapter Pattern
 * <p>
 * 用于将一个类的接口转换成另一个接口, 从而满足客户端对接口的需求
 * 在适配器模式中，适配器充当一个中间层, 通过实现目标接口并持有原始类的实例来实现对原始类的封装和转换
 * 客户端只需要调用目标接口中定义的方法即可完成对原始类的调用
 * <p>
 * 解决的问题
 * 1. 简单地说: 就是需要的东西就在你面前, 但却不能用, 而短时间又无法改造它, 于是我们就想办法去适配它
 * <p>
 * 关键代码
 * 1. 适配器继承或依赖已有的对象, 实现想要的目标接口
 * <p>
 * 优点
 * 1. 让任何两个没有关联的类一起运行
 * 2. 提高了类的复用
 * 3. 灵活性好
 * 4. 解决接口不兼容问题
 * <p>
 * 缺点
 * 1. 增加代码复杂度
 * 2. 可能会影响系统性能
 */
@Slf4j
public class AdapterPattern {


    public static void main(String[] args) {
        AudioPlayer audioPlayer = new AudioPlayer();
        audioPlayer.play("mp3", "haha");
        audioPlayer.play("vlc", "xixi");
        audioPlayer.play("mp4", "hehe");
        //
        StudentService studentService = new StudentServiceImpl();
        System.out.println(studentService.select());
        StudentAdapter studentAdapter = new StudentAdapter();
        System.out.println(studentAdapter.select());

    }


    public interface MediaPlayer {
        void play(String audioType, String fileName);
    }

    public interface AdvanceMediaPlayer {
        void playVlc(String fileName);

        void planMp4(String fileName);
    }

    public static class VlcPlayer implements AdvanceMediaPlayer {
        @Override
        public void playVlc(String fileName) {
            System.out.println("播放vlc：" + fileName);
        }

        @Override
        public void planMp4(String fileName) {
        }
    }

    public static class Mp4Player implements AdvanceMediaPlayer {
        @Override
        public void playVlc(String fileName) {
        }

        @Override
        public void planMp4(String fileName) {
            System.out.println("播放mp4：" + fileName);
        }
    }

    /**
     * MediaPlayer 接口的适配器类
     */
    public static class MediaAdapter implements MediaPlayer {

        AdvanceMediaPlayer advanceMediaPlayer;

        public MediaAdapter(String audioType) {
            if ("vlc".equals(audioType)) {
                advanceMediaPlayer = new VlcPlayer();
            } else if ("mp4".equals(audioType)) {
                advanceMediaPlayer = new Mp4Player();
            }
        }

        @Override
        public void play(String audioType, String fileName) {
            if ("vlc".equals(audioType)) {
                advanceMediaPlayer.playVlc(fileName);
            } else if ("mp4".equals(audioType)) {
                advanceMediaPlayer.planMp4(fileName);
            }
        }
    }

    public static class AudioPlayer implements MediaPlayer {

        MediaAdapter mediaAdapter;

        @Override
        public void play(String audioType, String fileName) {
            if ("mp3".equals(audioType)) {
                System.out.println("播放mp3: " + fileName);
            } else if ("vlc".equals(audioType) || "mp4".equals(audioType)) {
                mediaAdapter = new MediaAdapter(audioType);
                mediaAdapter.play(audioType, fileName);
            } else {
                System.out.println("所播放的文件格式不正确");
            }
        }
    }



    /*
    StudentService 提供 Student 查询功能, 封装 id 和 name 属性
    StudentAdapter 适配器组合 StudentService, 在 StudentService 原有的基础上提供封装 age 的功能
     */

    public interface StudentService {
        Student select();
    }

    public static class StudentServiceImpl implements StudentService {

        @Override
        public Student select() {
            log.info("select student from mysql");
            return Student.builder().id(1).name("name").build();
        }
    }

    public static class StudentAdapter implements StudentService {

        private final StudentService studentService = new StudentServiceImpl();

        @Override
        public Student select() {
            // 调用原功能
            Student student = studentService.select();
            // 适配器新增功能
            student.setAge(18);
            return student;
        }
    }


}
